import React, {Component} from 'react';
import {Animated, PanResponder} from 'react-native';
import ImageEditor from '@react-native-community/image-editor';
import RNImageRotate from 'react-native-image-rotate';
import PropTypes from 'prop-types';
import {SCREEN_WIDTH, SCREEN_HEIGHT, W, H, Q} from '../components/Cropper/Cropper.constants';
import Cropper from '../components/Cropper/Cropper.component';
import {getCropperLimits} from '../utils';

class CropperPage extends Component {
    constructor(props) {
        super(props);
        const {imageWidth, imageHeight, BORDER_WIDTH} = props;
        const W_INT = W - (2 * BORDER_WIDTH);
        const H_INT = H - (2 * BORDER_WIDTH);
        const {
            TOP_LIMIT,
            LEFT_LIMIT,
            BOTTOM_LIMIT,
            RIGHT_LIMIT,
            DIFF
        } = getCropperLimits(imageWidth, imageHeight, props.initialRotation, W_INT, H_INT, W, H, BORDER_WIDTH, Q);

        const TOP_VALUE = props.TOP_VALUE !== 0 ? props.TOP_VALUE : TOP_LIMIT;
        const LEFT_VALUE = props.LEFT_VALUE !== 0 ? props.LEFT_VALUE : LEFT_LIMIT;
        const BOTTOM_VALUE = props.BOTTOM_VALUE !== 0 ? props.BOTTOM_VALUE : BOTTOM_LIMIT;
        const RIGHT_VALUE = props.RIGHT_VALUE !== 0 ? props.RIGHT_VALUE : RIGHT_LIMIT;

        const topOuterPosition = new Animated.ValueXY({x: LEFT_VALUE - BORDER_WIDTH, y: TOP_VALUE - BORDER_WIDTH});
        const topOuterPanResponder = new PanResponder.create({onStartShouldSetPanResponder: () => false});
        const leftOuterPosition = new Animated.ValueXY({x: LEFT_VALUE - BORDER_WIDTH, y: TOP_VALUE - BORDER_WIDTH});
        const leftOuterPanResponder = new PanResponder.create({onStartShouldSetPanResponder: () => false});
        const bottomOuterPosition = new Animated.ValueXY({
            x: LEFT_VALUE - BORDER_WIDTH,
            y: SCREEN_HEIGHT - BOTTOM_VALUE
        });
        const bottomOuterPanResponder = new PanResponder.create({onStartShouldSetPanResponder: () => false});
        const rightOuterPosition = new Animated.ValueXY({x: SCREEN_WIDTH - RIGHT_VALUE, y: TOP_VALUE - BORDER_WIDTH});
        const rightOuterPanResponder = new PanResponder.create({onStartShouldSetPanResponder: () => false});

        const topPosition = new Animated.ValueXY({x: LEFT_VALUE - BORDER_WIDTH, y: TOP_VALUE - BORDER_WIDTH});
        const topPanResponder = this.initSidePanResponder('topPosition');
        const leftPosition = new Animated.ValueXY({x: LEFT_VALUE - BORDER_WIDTH, y: TOP_VALUE - BORDER_WIDTH});
        const leftPanResponder = this.initSidePanResponder('leftPosition');
        const bottomPosition = new Animated.ValueXY({x: LEFT_VALUE - BORDER_WIDTH, y: SCREEN_HEIGHT - BOTTOM_VALUE});
        const bottomPanResponder = this.initSidePanResponder('bottomPosition');
        const rightPosition = new Animated.ValueXY({
            x: SCREEN_WIDTH - RIGHT_VALUE,
            y: TOP_VALUE - BORDER_WIDTH - (DIFF / 2)
        });
        const rightPanResponder = this.initSidePanResponder('rightPosition');

        const topLeftPosition = new Animated.ValueXY({x: LEFT_VALUE - BORDER_WIDTH, y: TOP_VALUE - BORDER_WIDTH});
        const topLeftPanResponder = this.initCornerPanResponder('topPosition', 'leftPosition');
        const bottomLeftPosition = new Animated.ValueXY({
            x: LEFT_VALUE - BORDER_WIDTH,
            y: SCREEN_HEIGHT - BOTTOM_VALUE
        });
        const bottomLeftPanResponder = this.initCornerPanResponder('bottomPosition', 'leftPosition');
        const bottomRightPosition = new Animated.ValueXY({
            x: SCREEN_WIDTH - RIGHT_VALUE,
            y: SCREEN_HEIGHT - BOTTOM_VALUE
        });
        const bottomRightPanResponder = this.initCornerPanResponder('bottomPosition', 'rightPosition');
        const topRightPosition = new Animated.ValueXY({x: SCREEN_WIDTH - RIGHT_VALUE, y: TOP_VALUE - BORDER_WIDTH});
        const topRightPanResponder = this.initCornerPanResponder('topPosition', 'rightPosition');

        const rectanglePosition = new Animated.ValueXY({x: LEFT_VALUE, y: TOP_VALUE});
        const rectanglePanResponder = this.initRectanglePanResponder();

        this.state = {
            topOuterPosition,
            topOuterPanResponder,
            leftOuterPosition,
            leftOuterPanResponder,
            bottomOuterPosition,
            bottomOuterPanResponder,
            rightOuterPosition,
            rightOuterPanResponder,

            topPosition,
            topPanResponder,
            leftPosition,
            leftPanResponder,
            bottomPosition,
            bottomPanResponder,
            rightPosition,
            rightPanResponder,

            topLeftPosition,
            topLeftPanResponder,
            bottomLeftPosition,
            bottomLeftPanResponder,
            bottomRightPosition,
            bottomRightPanResponder,
            topRightPosition,
            topRightPanResponder,

            rectanglePosition,
            rectanglePanResponder,

            TOP_LIMIT,
            LEFT_LIMIT,
            BOTTOM_LIMIT,
            RIGHT_LIMIT,

            TOP_VALUE,
            LEFT_VALUE,
            BOTTOM_VALUE,
            RIGHT_VALUE,
            rotation: props.initialRotation,
        };
        this.isRectangleMoving = false;

    }

    onCancel = () => {
        this.props.onCancel();
    }

    getTopOuterStyle = () => {
        return {
            ...this.state.topOuterPosition.getLayout(),
            top: this.state.TOP_LIMIT,
            left: this.state.LEFT_LIMIT,
            height: Animated.add(this.props.BORDER_WIDTH - this.state.TOP_LIMIT, this.state.topPosition.y),
            width: W,
            backgroundColor: `rgba(0, 0, 0, ${this.props.NOT_SELECTED_AREA_OPACITY})`,
        };
    }

    getLeftOuterStyle = () => {
        return {
            ...this.state.leftOuterPosition.getLayout(),
            top: Animated.add(this.props.BORDER_WIDTH, this.state.topPosition.y),
            left: this.state.LEFT_LIMIT,
            height: Animated.add(
                -this.props.BORDER_WIDTH,
                Animated.add(
                    this.state.bottomPosition.y,
                    Animated.multiply(-1, this.state.topPosition.y)
                )
            ),
            width: Animated.add(this.props.BORDER_WIDTH - this.state.LEFT_LIMIT, this.state.leftPosition.x),
            backgroundColor: `rgba(0, 0, 0, ${this.props.NOT_SELECTED_AREA_OPACITY})`,
        };
    }

    getBottomOuterStyle = () => {
        return {
            ...this.state.bottomOuterPosition.getLayout(),
            top: this.state.bottomPosition.y,
            left: this.state.LEFT_LIMIT,
            height: Animated.add(
                SCREEN_HEIGHT - this.state.BOTTOM_LIMIT,
                Animated.multiply(-1, this.state.bottomPosition.y)
            ),
            width: W,
            backgroundColor: `rgba(0, 0, 0, ${this.props.NOT_SELECTED_AREA_OPACITY})`,
        };
    }

    getRightOuterStyle = () => {
        return {
            ...this.state.rightOuterPosition.getLayout(),
            top: Animated.add(this.props.BORDER_WIDTH, this.state.topPosition.y),
            left: this.state.rightPosition.x,
            height: Animated.add(
                -this.props.BORDER_WIDTH,
                Animated.add(
                    this.state.bottomPosition.y,
                    Animated.multiply(-1, this.state.topPosition.y)
                )
            ),
            right: this.state.RIGHT_LIMIT,
            backgroundColor: `rgba(0, 0, 0, ${this.props.NOT_SELECTED_AREA_OPACITY})`,
        };
    }

    getTopLeftStyle = () => {
        return {
            ...this.state.topLeftPosition.getLayout(),
            top: this.state.topPosition.y,
            left: this.state.leftPosition.x,
            width: this.props.BORDER_WIDTH,
            paddingBottom: this.props.BORDER_WIDTH,
        };
    }

    getBottomLeftStyle = () => {
        return {
            ...this.state.bottomLeftPosition.getLayout(),
            top: this.state.bottomPosition.y,
            left: this.state.leftPosition.x,
            width: this.props.BORDER_WIDTH,
            paddingTop: this.props.BORDER_WIDTH,
        };
    }

    getBottomRightStyle = () => {
        return {
            ...this.state.bottomRightPosition.getLayout(),
            top: this.state.bottomPosition.y,
            left: this.state.rightPosition.x,
            height: this.props.BORDER_WIDTH,
            paddingLeft: this.props.BORDER_WIDTH,
        };
    }

    getTopRightStyle = () => {
        return {
            ...this.state.topRightPosition.getLayout(),
            top: this.state.topPosition.y,
            left: this.state.rightPosition.x,
            height: this.props.BORDER_WIDTH,
            paddingLeft: this.props.BORDER_WIDTH,
        };
    }

    getTopSideStyle = () => {
        return {
            ...this.state.topPosition.getLayout(),
            left: Animated.add(this.props.BORDER_WIDTH, this.state.leftPosition.x),
            width: Animated.add(
                -this.props.BORDER_WIDTH,
                Animated.add(
                    this.state.rightPosition.x,
                    Animated.multiply(-1, this.state.leftPosition.x)
                )
            ),
            paddingBottom: this.props.BORDER_WIDTH,
        };
    }

    getLeftSideStyle = () => {
        return {
            ...this.state.leftPosition.getLayout(),
            top: Animated.add(this.props.BORDER_WIDTH, this.state.topPosition.y),
            height: Animated.add(
                -this.props.BORDER_WIDTH,
                Animated.add(
                    this.state.bottomPosition.y,
                    Animated.multiply(-1, this.state.topPosition.y)
                ),
            ),
            paddingLeft: this.props.BORDER_WIDTH,
        };
    }

    getBottomSideStyle = () => {
        return {
            ...this.state.bottomPosition.getLayout(),
            left: Animated.add(this.props.BORDER_WIDTH, this.state.leftPosition.x),
            width: Animated.add(
                -this.props.BORDER_WIDTH,
                Animated.add(
                    this.state.rightPosition.x,
                    Animated.multiply(-1, this.state.leftPosition.x)
                )
            ),
            paddingTop: this.props.BORDER_WIDTH,
        };
    }

    getRightSideStyle = () => {
        return {
            ...this.state.rightPosition.getLayout(),
            top: Animated.add(this.props.BORDER_WIDTH, this.state.topPosition.y),
            height: Animated.add(
                -this.props.BORDER_WIDTH,
                Animated.add(
                    this.state.bottomPosition.y,
                    Animated.multiply(-1, this.state.topPosition.y)
                )
            ),
            paddingLeft: this.props.BORDER_WIDTH,
        };
    }

    getRectangleStyle = () => {
        return {
            ...this.state.rectanglePosition.getLayout(),
            top: Animated.add(this.props.BORDER_WIDTH, this.state.topPosition.y),
            left: Animated.add(this.props.BORDER_WIDTH, this.state.leftPosition.x),
            width: Animated.add(
                -this.props.BORDER_WIDTH,
                Animated.add(
                    this.state.rightPosition.x,
                    Animated.multiply(-1, this.state.leftPosition.x)
                )
            ),
            height: Animated.add(
                -this.props.BORDER_WIDTH,
                Animated.add(
                    this.state.bottomPosition.y,
                    Animated.multiply(-1, this.state.topPosition.y)
                )
            ),
            zIndex: 3
        };
    }

    getImageStyle = () => {
        const DIFF = this.state.topPosition.y._value - this.state.rightPosition.y._value;
        return {
            position: 'absolute',
            top: this.state.TOP_LIMIT - DIFF,
            left: this.state.LEFT_LIMIT + DIFF,
            bottom: this.state.BOTTOM_LIMIT - DIFF,
            right: this.state.RIGHT_LIMIT + DIFF,
            resizeMode: 'contain',
            transform: [
                {rotate: `${this.state.rotation.toString()}deg`},
            ],
        };
    }

    isAllowedToMoveTopSide = (gesture) => {
        return this.state.topPosition.y._offset + gesture.dy >= this.state.TOP_LIMIT - this.props.BORDER_WIDTH &&
            this.state.topPosition.y._offset + gesture.dy + this.props.BORDER_WIDTH + 1 < this.state.bottomPosition.y._offset;
    }
    isAllowedToMoveLeftSide = (gesture) => {
        return this.state.leftPosition.x._offset + gesture.dx >= this.state.LEFT_LIMIT - this.props.BORDER_WIDTH &&
            this.state.leftPosition.x._offset + gesture.dx + this.props.BORDER_WIDTH + 1 < this.state.rightPosition.x._offset;
    }
    isAllowedToMoveBottomSide = (gesture) => {
        return this.state.bottomPosition.y._offset + gesture.dy <= SCREEN_HEIGHT - this.state.BOTTOM_LIMIT &&
            this.state.topPosition.y._offset + this.props.BORDER_WIDTH + 1 < this.state.bottomPosition.y._offset + gesture.dy;
    }
    isAllowedToMoveRightSide = (gesture) => {
        return this.state.rightPosition.x._offset + gesture.dx <= SCREEN_WIDTH - this.state.RIGHT_LIMIT &&
            this.state.leftPosition.x._offset + this.props.BORDER_WIDTH + 1 < this.state.rightPosition.x._offset + gesture.dx;
    }

    isAllowedToMove = (position, gesture) => {
        if (position === 'topPosition') {
            return this.isAllowedToMoveTopSide(gesture);
        }
        if (position === 'leftPosition') {
            return this.isAllowedToMoveLeftSide(gesture);
        }
        if (position === 'bottomPosition') {
            return this.isAllowedToMoveBottomSide(gesture);
        }
        if (position === 'rightPosition') {
            return this.isAllowedToMoveRightSide(gesture);
        }
    }

    initSidePanResponder = (position) => {
        return PanResponder.create({
            onStartShouldSetPanResponder: () => !this.isRectangleMoving,
            onPanResponderMove: (event, gesture) => {
                if (this.isAllowedToMove(position, gesture)) {
                    this.state[position].setValue({x: gesture.dx, y: gesture.dy});
                }
            },
            onPanResponderRelease: () => {
                // make to not reset position
                this.state.topPosition.flattenOffset();
                this.state.leftPosition.flattenOffset();
                this.state.bottomPosition.flattenOffset();
                this.state.rightPosition.flattenOffset();
            },
            onPanResponderGrant: () => {
                this.state.topPosition.setOffset({
                    x: this.state.topPosition.x._value,
                    y: this.state.topPosition.y._value
                });
                this.state.leftPosition.setOffset({
                    x: this.state.leftPosition.x._value,
                    y: this.state.leftPosition.y._value
                });
                this.state.bottomPosition.setOffset({
                    x: this.state.bottomPosition.x._value,
                    y: this.state.bottomPosition.y._value
                });
                this.state.rightPosition.setOffset({
                    x: this.state.rightPosition.x._value,
                    y: this.state.rightPosition.y._value
                });

                this.state.topPosition.setValue({x: 0, y: 0});
                this.state.leftPosition.setValue({x: 0, y: 0});
                this.state.bottomPosition.setValue({x: 0, y: 0});
                this.state.rightPosition.setValue({x: 0, y: 0});
            }
        });
    }

    initRectanglePanResponder = () => {
        return PanResponder.create({
            onStartShouldSetPanResponder: () => !this.isRectangleMoving,
            onPanResponderMove: (event, gesture) => {
                this.state.topPosition.setValue({x: gesture.dx, y: gesture.dy});
                this.state.leftPosition.setValue({x: gesture.dx, y: gesture.dy});
                this.state.bottomPosition.setValue({x: gesture.dx, y: gesture.dy});
                this.state.rightPosition.setValue({x: gesture.dx, y: gesture.dy});
            },
            onPanResponderRelease: () => {
                this.isRectangleMoving = true;
                // make to not reset position
                this.state.topPosition.flattenOffset();
                this.state.leftPosition.flattenOffset();
                this.state.bottomPosition.flattenOffset();
                this.state.rightPosition.flattenOffset();

                const width = this.state.rightPosition.x._value - this.state.leftPosition.x._value - this.props.BORDER_WIDTH;
                const height = this.state.bottomPosition.y._value - this.state.topPosition.y._value - this.props.BORDER_WIDTH;
                let isOutside = false;

                if (this.state.leftPosition.x._value < this.state.LEFT_LIMIT - this.props.BORDER_WIDTH) {
                    isOutside = true;
                    Animated.parallel([
                        Animated.spring(this.state.leftPosition.x, {toValue: this.state.LEFT_LIMIT - this.props.BORDER_WIDTH}),
                        Animated.spring(this.state.rightPosition.x, {toValue: this.state.LEFT_LIMIT + width})
                    ]).start(
                        () => {
                            this.isRectangleMoving = false;
                        }
                    );
                }
                if (this.state.topPosition.y._value < this.state.TOP_LIMIT - this.props.BORDER_WIDTH) {
                    isOutside = true;
                    Animated.parallel([
                        Animated.spring(this.state.topPosition.y, {toValue: this.state.TOP_LIMIT - this.props.BORDER_WIDTH}),
                        Animated.spring(this.state.bottomPosition.y, {toValue: this.state.TOP_LIMIT + height})
                    ]).start(
                        () => {
                            this.isRectangleMoving = false;
                        }
                    );
                }
                if (width + this.state.leftPosition.x._value + this.props.BORDER_WIDTH > SCREEN_WIDTH - this.state.RIGHT_LIMIT) {
                    isOutside = true;
                    Animated.parallel([
                        Animated.spring(this.state.leftPosition.x, {toValue: SCREEN_WIDTH - this.state.RIGHT_LIMIT - width - this.props.BORDER_WIDTH}),
                        Animated.spring(this.state.rightPosition.x, {toValue: SCREEN_WIDTH - this.state.RIGHT_LIMIT})
                    ]).start(
                        () => {
                            this.isRectangleMoving = false;
                        }
                    );
                }
                if (height + this.state.topPosition.y._value + this.props.BORDER_WIDTH > SCREEN_HEIGHT - this.state.BOTTOM_LIMIT) {
                    isOutside = true;
                    Animated.parallel([
                        Animated.spring(this.state.topPosition.y, {toValue: SCREEN_HEIGHT - this.state.BOTTOM_LIMIT - height - this.props.BORDER_WIDTH}),
                        Animated.spring(this.state.bottomPosition.y, {toValue: SCREEN_HEIGHT - this.state.BOTTOM_LIMIT})
                    ]).start(
                        () => {
                            this.isRectangleMoving = false;
                        }
                    );
                }
                if (!isOutside) {
                    this.isRectangleMoving = false;
                }
            },
            onPanResponderGrant: () => {
                this.state.topPosition.setOffset({
                    x: this.state.topPosition.x._value,
                    y: this.state.topPosition.y._value
                });
                this.state.leftPosition.setOffset({
                    x: this.state.leftPosition.x._value,
                    y: this.state.leftPosition.y._value
                });
                this.state.bottomPosition.setOffset({
                    x: this.state.bottomPosition.x._value,
                    y: this.state.bottomPosition.y._value
                });
                this.state.rightPosition.setOffset({
                    x: this.state.rightPosition.x._value,
                    y: this.state.rightPosition.y._value
                });
                this.state.topPosition.setValue({x: 0, y: 0});
                this.state.leftPosition.setValue({x: 0, y: 0});
                this.state.bottomPosition.setValue({x: 0, y: 0});
                this.state.rightPosition.setValue({x: 0, y: 0});
            }
        });
    }

    initCornerPanResponder = (pos1, pos2) => {
        return PanResponder.create({
            onStartShouldSetPanResponder: () => !this.isRectangleMoving,
            onPanResponderMove: (event, gesture) => {
                if (this.isAllowedToMove(pos1, gesture)) {
                    this.state[pos1].setValue({x: gesture.dx, y: gesture.dy});
                }
                if (this.isAllowedToMove(pos2, gesture)) {
                    this.state[pos2].setValue({x: gesture.dx, y: gesture.dy});
                }
            },
            onPanResponderRelease: () => {
                this.state.topPosition.flattenOffset();
                this.state.leftPosition.flattenOffset();
                this.state.bottomPosition.flattenOffset();
                this.state.rightPosition.flattenOffset();
            },
            onPanResponderGrant: () => {
                this.state.topPosition.setOffset({
                    x: this.state.topPosition.x._value,
                    y: this.state.topPosition.y._value
                });
                this.state.leftPosition.setOffset({
                    x: this.state.leftPosition.x._value,
                    y: this.state.leftPosition.y._value
                });
                this.state.bottomPosition.setOffset({
                    x: this.state.bottomPosition.x._value,
                    y: this.state.bottomPosition.y._value
                });
                this.state.rightPosition.setOffset({
                    x: this.state.rightPosition.x._value,
                    y: this.state.rightPosition.y._value
                });

                this.state.topPosition.setValue({x: 0, y: 0});
                this.state.leftPosition.setValue({x: 0, y: 0});
                this.state.bottomPosition.setValue({x: 0, y: 0});
                this.state.rightPosition.setValue({x: 0, y: 0});
            }
        });
    }

    setCropBoxLimits = ({TOP_LIMIT, LEFT_LIMIT, BOTTOM_LIMIT, RIGHT_LIMIT}) => {
        this.setState({
            TOP_LIMIT,
            LEFT_LIMIT,
            BOTTOM_LIMIT,
            RIGHT_LIMIT
        });
    }

    setCropBoxValues = ({TOP_VALUE, LEFT_VALUE, BOTTOM_VALUE, RIGHT_VALUE}) => {
        this.setState({
            TOP_VALUE,
            LEFT_VALUE,
            BOTTOM_VALUE,
            RIGHT_VALUE
        });
    }

    setCropBoxRotation = (rotation) => {
        this.setState({rotation});
    }

    rotate90 = () => {
        this.setCropBoxRotation((360 + (this.state.rotation - 90)) % 360);
    }

    onRotate = () => {
        const W_INT = W - (2 * this.props.BORDER_WIDTH);
        const H_INT = H - (2 * this.props.BORDER_WIDTH);
        let imageWidth = 0;
        let imageHeight = 0;
        let rotation = 0;
        if (this.state.rotation % 180 === 90) {
            imageWidth = this.props.imageWidth > 0 ? this.props.imageWidth : 1280; // 340
            imageHeight = this.props.imageHeight > 0 ? this.props.imageHeight : 747; // 500
            rotation = 0;
        } else {
            imageWidth = SCREEN_WIDTH - this.state.LEFT_LIMIT - this.state.RIGHT_LIMIT;
            imageHeight = SCREEN_HEIGHT - this.state.TOP_LIMIT - this.state.BOTTOM_LIMIT;
            rotation = 90;
        }
        const {
            TOP_LIMIT,
            LEFT_LIMIT,
            BOTTOM_LIMIT,
            RIGHT_LIMIT,
            DIFF
        } = getCropperLimits(imageWidth, imageHeight, rotation, W_INT, H_INT, W, H, this.props.BORDER_WIDTH, Q);
        this.rotate90();
        this.setCropBoxLimits({TOP_LIMIT, LEFT_LIMIT, BOTTOM_LIMIT, RIGHT_LIMIT});
        const startPositionBeforeRotationX = (this.state.leftPosition.x._value - this.state.LEFT_LIMIT) + this.props.BORDER_WIDTH;
        const startPositionBeforeRotationY = (this.state.topPosition.y._value - this.state.TOP_LIMIT) + this.props.BORDER_WIDTH;
        const imageWidthBeforeRotation = SCREEN_WIDTH - this.state.RIGHT_LIMIT - this.state.LEFT_LIMIT;
        const imageHeightBeforeRotation = SCREEN_HEIGHT - this.state.BOTTOM_LIMIT - this.state.TOP_LIMIT;
        const rectangleWidthBeforeRotation = this.state.rightPosition.x._value - this.state.leftPosition.x._value - this.props.BORDER_WIDTH;
        const rectangleHeightBeforeRotation = this.state.bottomPosition.y._value - this.state.topPosition.y._value - this.props.BORDER_WIDTH;
        const imageWidthAfterRotation = SCREEN_WIDTH - RIGHT_LIMIT - LEFT_LIMIT;
        const imageHeightAfterRotation = SCREEN_HEIGHT - BOTTOM_LIMIT - TOP_LIMIT;
        const rectangleWidthAfterRotation = (imageWidthAfterRotation * rectangleHeightBeforeRotation) / imageHeightBeforeRotation;
        const rectangleHeightAfterRotation = (imageHeightAfterRotation * rectangleWidthBeforeRotation) / imageWidthBeforeRotation;
        const startPositionAfterRotationX = (startPositionBeforeRotationY * imageWidthAfterRotation) / imageHeightBeforeRotation;
        const startPositionAfterRotationY = (
            (imageWidthBeforeRotation - startPositionBeforeRotationX - rectangleWidthBeforeRotation) * imageHeightAfterRotation
        ) / imageWidthBeforeRotation;

        this.state.topPosition.setValue({
            x: (LEFT_LIMIT + startPositionAfterRotationX) - this.props.BORDER_WIDTH,
            y: (TOP_LIMIT + startPositionAfterRotationY) - this.props.BORDER_WIDTH
        });
        this.state.leftPosition.setValue({
            x: (LEFT_LIMIT + startPositionAfterRotationX) - this.props.BORDER_WIDTH,
            y: (TOP_LIMIT + startPositionAfterRotationY) - this.props.BORDER_WIDTH
        });
        this.state.bottomPosition.setValue({
            x: (LEFT_LIMIT + startPositionAfterRotationX) - this.props.BORDER_WIDTH,
            y: TOP_LIMIT + startPositionAfterRotationY + rectangleHeightAfterRotation
        });
        this.state.rightPosition.setValue({
            x: LEFT_LIMIT + startPositionAfterRotationX + rectangleWidthAfterRotation,
            y: (TOP_LIMIT + startPositionAfterRotationY) - this.props.BORDER_WIDTH - (DIFF / 2)
        });
        this.topOuter.setNativeProps({style: {top: TOP_LIMIT, height: 0}});
        this.leftOuter.setNativeProps({style: {left: LEFT_LIMIT, width: 0}});
        this.bottomOuter.setNativeProps({style: {top: BOTTOM_LIMIT, height: 0}});
        this.rightOuter.setNativeProps({style: {top: TOP_LIMIT, height: 0}});
    }

    onDone = () => {
        this.props.onStartCrop && this.props.onStartCrop();
        if (this.isRectangleMoving){
            this.props.onDone();
            return null;
        }
        //this.setState({ isSaving: true });
        const IMAGE_W = SCREEN_WIDTH - this.state.RIGHT_LIMIT - this.state.LEFT_LIMIT;
        const IMAGE_H = SCREEN_HEIGHT - this.state.BOTTOM_LIMIT - this.state.TOP_LIMIT;
        let x = (this.state.leftPosition.x._value - this.state.LEFT_LIMIT) + this.props.BORDER_WIDTH +this.props.editorDeviation;
        let y = (this.state.topPosition.y._value - this.state.TOP_LIMIT) + this.props.BORDER_WIDTH +this.props.editorDeviation;
        let width = this.state.rightPosition.x._value - this.state.leftPosition.x._value - this.props.BORDER_WIDTH - this.props.editorDeviation*2
        let height = this.state.bottomPosition.y._value - this.state.topPosition.y._value - this.props.BORDER_WIDTH - this.props.editorDeviation*2;
        let imageWidth = this.props.imageWidth > 0 ? this.props.imageWidth : 1280; // 340
        let imageHeight = this.props.imageHeight > 0 ? this.props.imageHeight : 747; // 500
        if (this.state.rotation % 180 === 90) {
            const pivot = imageWidth;
            imageWidth = imageHeight;
            imageHeight = pivot;
        }
        width = (width * imageWidth) / IMAGE_W ;
        height = (height * imageHeight) / IMAGE_H ;
        x = (x * imageWidth) / IMAGE_W ;
        y = (y * imageHeight) / IMAGE_H ;
        const cropData = {
            offset: {x, y},
            size: {width, height},
        };
        RNImageRotate.rotateImage(
            this.props.imageUri,
            this.state.rotation,
            (rotatedUri) => {
                //
                ImageEditor.cropImage(rotatedUri, cropData).then(url => {
                    console.log("Cropped image uri", url);
                    this.props.onDone(url);
                })
                // ImageEditor.cropImage(
                //     rotatedUri,
                //     cropData,
                //     (croppedUri) => {
                //         console.log("-------001-----")
                //         this.props.onDone(croppedUri);
                //     },
                //     (err) => {
                //         console.log('cropping error');
                //         console.log(err);
                //         this.props.onDone();
                //     }
                // );
                //
            },
            (err) => {
                alert(err);
                console.log(err);
                this.props.onDone();
            }
        );
    }

    render() {
        return (
            <Cropper
                imageUri={this.props.imageUri} // 'https://3.imimg.com/data3/SN/NO/MY-10244508/vertical-building-parking-500x500.jpg'
                footerComponent={this.props.footerComponent}
                editorComponent={this.props.editorComponent}
                getTopOuterStyle={this.getTopOuterStyle}
                getLeftOuterStyle={this.getLeftOuterStyle}
                getBottomOuterStyle={this.getBottomOuterStyle}
                getRightOuterStyle={this.getRightOuterStyle}
                getTopLeftStyle={this.getTopLeftStyle}
                getBottomLeftStyle={this.getBottomLeftStyle}
                getBottomRightStyle={this.getBottomRightStyle}
                getTopRightStyle={this.getTopRightStyle}
                getTopSideStyle={this.getTopSideStyle}
                getLeftSideStyle={this.getLeftSideStyle}
                getBottomSideStyle={this.getBottomSideStyle}
                getRightSideStyle={this.getRightSideStyle}
                getRectangleStyle={this.getRectangleStyle}
                getImageStyle={this.getImageStyle}
                onDone={this.onDone}
                onRotate={this.onRotate}
                onCancel={this.onCancel}
                topOuterPanResponder={this.state.topOuterPanResponder}
                leftOuterPanResponder={this.state.leftOuterPanResponder}
                bottomOuterPanResponder={this.state.bottomOuterPanResponder}
                rightOuterPanResponder={this.state.rightOuterPanResponder}
                topPanResponder={this.state.topPanResponder}
                leftPanResponder={this.state.leftPanResponder}
                bottomPanResponder={this.state.bottomPanResponder}
                rightPanResponder={this.state.rightPanResponder}
                topLeftPanResponder={this.state.topLeftPanResponder}
                bottomLeftPanResponder={this.state.bottomLeftPanResponder}
                bottomRightPanResponder={this.state.bottomRightPanResponder}
                topRightPanResponder={this.state.topRightPanResponder}
                rectanglePanResponder={this.state.rectanglePanResponder}
                topOuterRef={ref => {
                    this.topOuter = ref;
                }}
                leftOuterRef={ref => {
                    this.leftOuter = ref;
                }}
                bottomOuterRef={ref => {
                    this.bottomOuter = ref;
                }}
                rightOuterRef={ref => {
                    this.rightOuter = ref;
                }}
            />
        );
    }
}

CropperPage.propTypes = {
    footerComponent: PropTypes.object,
    editorComponent: PropTypes.object,
    onStartCrop:PropTypes.func,
    onDone: PropTypes.func,
    onCancel: PropTypes.func,
    imageUri: PropTypes.string,
    imageWidth: PropTypes.number,
    imageHeight: PropTypes.number,
    TOP_VALUE: PropTypes.number,
    LEFT_VALUE: PropTypes.number,
    BOTTOM_VALUE: PropTypes.number,
    RIGHT_VALUE: PropTypes.number,
    initialRotation: PropTypes.number,
    NOT_SELECTED_AREA_OPACITY: PropTypes.number,
    BORDER_WIDTH: PropTypes.number,
    editorDeviation: PropTypes.number,
};

export default CropperPage;
